package com.jfunit.java.helper;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.tools.ant.taskdefs.Echo;

import com.jfunit.java.annotation.Action;
import com.jfunit.java.bean.Handler;
import com.jfunit.java.bean.Request;
import com.jfunit.java.util.StringUtil;

/**
 * 控制器助手类
 * 
 * @author Administrator
 *
 */
public class ControllerHelper {

    // 用于存放请求与处理器的映射关系，简称Action Map
    private static final Map<Request, Handler> ACTION_MAP = new HashMap<Request, Handler>();

    static {
        // 定义两个 Action Map
        Map<Request, Handler> commonActionMap = new HashMap<Request, Handler>(); // 存放普通 Action Map
        Map<Request, Handler> regexpActionMap = new HashMap<Request, Handler>(); // 存放带有正则表达式的
                                                                                 // Action Map

        // 获取所有的Controller类
        Set<Class<?>> controllerClassSet = ClassHelper.getControllerClassSet();
        if (CollectionUtils.isNotEmpty(controllerClassSet)) {
            // 遍历这些controller类
            for (Class<?> controllerClass : controllerClassSet) {
                // 获取controller类中定义的方法
                Method[] methods = controllerClass.getDeclaredMethods();// 获取所有的 方法
                if (ArrayUtils.isNotEmpty(methods)) {
                    // 遍历这些controller类中的方法
                    for (Method method : methods) {
                        // 判断当前方法是否有Action注解
                        if (method.isAnnotationPresent(Action.class)) {// 找到action注解的方法
                            // 从Action注解中获取URL映射规则
                            Action action = method.getAnnotation(Action.class);
                            // 处理 Action 方法
                            Handler handler = new Handler(controllerClass, method);// hander保存的是对应的类 和 方法
                            String requestPath = action.value();
                            // 判断 Request Path 中是否带有占位符
                            if (requestPath.matches(".+\\{\\w+\\}.*")) {
                                // 将请求路径中的占位符 {\w+} 转换为正则表达式 (\\w+)
                                requestPath = StringUtil.replaceAll(requestPath, "\\{\\w+\\}", "(\\\\w+)");
                                
                                //记录正则参数位置及名称
                                Map<Integer, Object> PathVariableParam = new HashMap<Integer, Object>();
                                Pattern pattern = Pattern.compile("\\{(\\w*)\\}"); 
                                Matcher matcher = pattern.matcher(action.value()); 
                                int i = 1;
                                while(matcher.find()){ 
                                    PathVariableParam.put(i++, matcher.group(1));
                                }
                                handler.setPathVariableParam(PathVariableParam);
                                // 将 Requester 与 Handler 放入 Regexp Action Map 中
                                Request request = new Request(action.method().toLowerCase(), requestPath);
                                regexpActionMap.put(request, handler);
                            } else {
                                // 将 Requester 与 Handler 放入 Common Action Map 中
                                Request request = new Request(action.method().toLowerCase(), requestPath);
                                commonActionMap.put(request, handler);
                            }

                            // Request request = new Request(action.method().toLowerCase(),
                            // action.value());
                            // ACTION_MAP.put(request, handler);// 把 请求的方法 和路径封装成的request对象,和 处理
                            // 该路径的方法,所管理.到时候就能找得到执行谁了
                        }
                    }

                    // 初始化最终的 Action Map（将 Common 放在 Regexp 前面）
                    ACTION_MAP.putAll(commonActionMap);
                    ACTION_MAP.putAll(regexpActionMap);
                }
            }
        }
    }

    /**
     * 获取Handler
     * 
     * @param requestMethod
     * @param requestPath
     * @return
     */
    public static Handler getHandler(String currentRequestMethod, String currentRequestPath) {
        Request request = new Request(currentRequestMethod, currentRequestPath);

        //完全匹陪，无正则参数
        if (ACTION_MAP.containsKey(request)) {
            return ACTION_MAP.get(request);
        } else {
            // 定义一个 Handler
            Handler handler = null;
            for (Map.Entry<Request, Handler> actionEntry : ACTION_MAP.entrySet()) {
                // 从request中获取相关属
                request = actionEntry.getKey();
                String requestMethod = request.getRequestMethod();
                String requestPath = request.getRequestPath();// 正则表达式
                // 获取请求路径匹配器（使用正则表达式匹配请求路径并从中获取相应的请求参数）
                Matcher requestPathMatcher = Pattern.compile(requestPath).matcher(currentRequestPath);
                // 判断请求方法与请求路径是否同时匹配
                if (requestMethod.equalsIgnoreCase(currentRequestMethod) && requestPathMatcher.matches()) {
                    // 获取Handler及其相关属性
                    handler = actionEntry.getValue();
                    // 设置请求路径匹配器
                    if (handler != null) {
                        handler.setRequestPathMatcher(requestPathMatcher);
                    }  
                    
                    // 若成功匹配，则终止循环
                    break;
                }
            }

            // 返回该 Handler
            return handler;
        }

    }

    /**
     * 获取 Action Map
     */
    public static Map<Request, Handler> getActionMap() {
        return ACTION_MAP;
    }
}
